extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include "animation_demo.h"

namespace script {

static bool _initialized = false;
static lua_State *_L = NULL;
static misc::SimpleList<ActionNode *> *actionlist = NULL;

static int L_action_add_show(lua_State *L)
{
    int n = 0;
    const char *objid = NULL;
    Uint32 timestamp = 0;

    if (!_initialized) {
        lua_pushstring(L, "lua_State not initialized.");
        return lua_error(L);
    }

    n = lua_gettop(L);
    if (n < 2) {
        lua_pushstring(L, "too few argument.");
        return lua_error(L);
    }

    if (!lua_isstring(L, 1)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    objid = lua_tostring(L, 1);

    if (!lua_isnumber(L, 2)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    timestamp = (Uint32)lua_tonumber(L, 2);

    //do
    action_add_show(actionlist, objid, timestamp);
    return 0;
}

static int L_action_add_hide(lua_State *L)
{
    int n = 0;
    const char *objid = NULL;
    Uint32 timestamp = 0;

    if (!_initialized) {
        lua_pushstring(L, "lua_State not initialized.");
        return lua_error(L);
    }

    n = lua_gettop(L);
    if (n < 2) {
        lua_pushstring(L, "too few argument.");
        return lua_error(L);
    }

    if (!lua_isstring(L, 1)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    objid = lua_tostring(L, 1);

    if (!lua_isnumber(L, 2)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    timestamp = (Uint32)lua_tonumber(L, 2);

    //do
    action_add_hide(actionlist, objid, timestamp);
    return 0;
}

static int L_action_add_move(lua_State *L)
{
    int n = 0;
    const char *objid = NULL;
    Uint32 timestamp = 0;
    Uint32 duration = 0;
    Sint16 dx = 0, dy = 0;

    if (!_initialized) {
        lua_pushstring(L, "lua_State not initialized.");
        return lua_error(L);
    }

    n = lua_gettop(L);
    if (n < 5) {
        lua_pushstring(L, "too few argument.");
        return lua_error(L);
    }

    if (!lua_isstring(L, 1)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    objid = lua_tostring(L, 1);

    if (!lua_isnumber(L, 2)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    timestamp = (Uint32)lua_tonumber(L, 2);

    if (!lua_isnumber(L, 3)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    duration = (Uint32)lua_tonumber(L, 3);

    if (!lua_isnumber(L, 4)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    dx = (Sint16)lua_tonumber(L, 4);

    if (!lua_isnumber(L, 5)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    dy = (Sint16)lua_tonumber(L, 5);

    //do
    action_add_move(actionlist, objid, timestamp, duration, dx, dy);
    return 0;
}

static int L_action_add_fadein(lua_State *L)
{
    int n = 0;
    const char *objid = NULL;
    Uint32 timestamp = 0;
    Uint32 duration = 0;

    if (!_initialized) {
        lua_pushstring(L, "lua_State not initialized.");
        return lua_error(L);
    }

    n = lua_gettop(L);
    if (n < 3) {
        lua_pushstring(L, "too few argument.");
        return lua_error(L);
    }

    if (!lua_isstring(L, 1)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    objid = lua_tostring(L, 1);

    if (!lua_isnumber(L, 2)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    timestamp = (Uint32)lua_tonumber(L, 2);

    if (!lua_isnumber(L, 3)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    duration = (Uint32)lua_tonumber(L, 3);

    //do
    action_add_fadein(actionlist, objid, timestamp, duration);
    return 0;
}

static int L_action_add_fadeout(lua_State *L)
{
    int n = 0;
    const char *objid = NULL;
    Uint32 timestamp = 0;
    Uint32 duration = 0;

    if (!_initialized) {
        lua_pushstring(L, "lua_State not initialized.");
        return lua_error(L);
    }

    n = lua_gettop(L);
    if (n < 3) {
        lua_pushstring(L, "too few argument.");
        return lua_error(L);
    }

    if (!lua_isstring(L, 1)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    objid = lua_tostring(L, 1);

    if (!lua_isnumber(L, 2)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    timestamp = (Uint32)lua_tonumber(L, 2);

    if (!lua_isnumber(L, 3)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    duration = (Uint32)lua_tonumber(L, 3);

    //do
    action_add_fadeout(actionlist, objid, timestamp, duration);
    return 0;
}

static int L_action_set_color(lua_State *L)
{
    int n = 0;
    const char *objid = NULL;
    Uint32 timestamp = 0;
    Uint8 r, g, b;

    if (!_initialized) {
        lua_pushstring(L, "lua_State not initialized.");
        return lua_error(L);
    }

    n = lua_gettop(L);
    if (n < 5) {
        lua_pushstring(L, "too few argument.");
        return lua_error(L);
    }

    if (!lua_isstring(L, 1)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    objid = lua_tostring(L, 1);

    if (!lua_isnumber(L, 2)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    timestamp = (Uint32)lua_tonumber(L, 2);

    if (!lua_isnumber(L, 3)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    r = (Uint8)lua_tonumber(L, 3);

    if (!lua_isnumber(L, 4)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    g = (Uint8)lua_tonumber(L, 4);

    if (!lua_isnumber(L, 5)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    b = (Uint8)lua_tonumber(L, 5);

    //do
    action_add_setcolor(actionlist, objid, timestamp, r, g, b);
    return 0;
}

static int L_action_set_text(lua_State *L)
{
    int n = 0;
    const char *objid = NULL;
    Uint32 timestamp = 0;
    const char *str = NULL;

    if (!_initialized) {
        lua_pushstring(L, "lua_State not initialized.");
        return lua_error(L);
    }

    n = lua_gettop(L);
    if (n < 3) {
        lua_pushstring(L, "too few argument.");
        return lua_error(L);
    }

    if (!lua_isstring(L, 1)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    objid = lua_tostring(L, 1);

    if (!lua_isnumber(L, 2)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    timestamp = (Uint32)lua_tonumber(L, 2);

    if (!lua_isstring(L, 3)) {
        lua_pushstring(L, "Incorrect argument.");
        return lua_error(L);
    }
    str = lua_tostring(L, 3);

    //do
    action_add_settext(actionlist, objid, timestamp, str);
    return 0;
}

int script_lua_init(misc::SimpleList<ActionNode *> *list)
{
    if (_initialized) {
        return 0;
    }

    if (list == NULL) {
        return -1;
    }

    actionlist = list;

    _L = luaL_newstate();
    if (_L == NULL) {
        return -1;
    }
    /* Opens all standard Lua libraries */
    luaL_openlibs(_L);
    /* register our functions */
    lua_register(_L, "widget_show", L_action_add_show);
    lua_register(_L, "widget_hide", L_action_add_hide);
    lua_register(_L, "widget_move", L_action_add_move);
    lua_register(_L, "widget_fadein", L_action_add_fadein);
    lua_register(_L, "widget_fadeout", L_action_add_fadeout);
    lua_register(_L, "widget_set_color", L_action_set_color);
    lua_register(_L, "widget_set_text", L_action_set_text);
    //lua_register(_L, "change_manapoint", change_manapoint);
    _initialized = true;
    return 0;
}

int script_lua_close()
{
    if (!_initialized) {
        return 0;
    }
    lua_close(_L);
    actionlist = NULL;
    _initialized = false;
    return 0;
}

int script_lua_dostr(const char *str)
{
    int ret = 0;
    if (str == NULL) {
        return -1;
    }
    ret = luaL_dostring(_L, str);
    if (ret != 0) {
        return -1;
    }
    return 0;
}

int script_lua_dofile(const char *filename)
{
    int ret = 0;
    if (filename == NULL) {
        return -1;
    }
    ret = luaL_dofile(_L, filename);
    if (ret != 0) {
        return -1;
    }
    return 0;
}


}
